home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Mac Game Programming Gurus
/
TricksOfTheMacGameProgrammingGurus.iso
/
More Source
/
C⁄C++
/
AIFF DSP v22
/
plugin_src
/
sintab.c
< prev
next >
Wrap
Text File
|
1995-01-30
|
3KB
|
97 lines
/* sine table generation & lookup code */
#include "aiff.h"
#include "sintab.h"
#include "num_input_macros.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define HALFPI 1.5707963 /* half of pi */
#define SINAMP 0x7FFF /* sine wave amplitude */
short sintab[QSIZ+1];
double round( double x )
{
double offset = 0.5;
if ( x < 0.0 ) offset = -offset;
return x + offset;
}
/* puts a 1st-quadrant sine table into sintab[] */
void get_sintab ( void )
{
short i;
sintab[0] = 0;
sintab[QSIZ] = SINAMP;
for (i=1; i < QSIZ; i++)
sintab[i] = round( SINAMP * sin( HALFPI * i / QSIZ ) );
}
/*
1. Small enough means that the correct last value is found where expected.
2. Does not deserve a call to exit because a file error here does not impede
function of program and therefore is not a fatal error.
*/
/* puts a full 4-quadrant sine table into sintab4[] using sintab() */
short *gen_sintab4 ( void )
{
unsigned short i;
short *sintab4, *tsintab4;
if (!(sintab4 = malloc( 2L*4*QSIZ )))
err( "Could not allocate 4-quadrant sine table memory" );
tsintab4 = sintab4;
for (i=0; i<4*QSIZ; i++)
*tsintab4++ = sin_tab( i );
return sintab4;
}
/* returns SINAMP * sin (pi/2 * tabi/QSIZ) using sintab[] */
/* tabi is assumed to be non-negative */
short sin_tab( short tabi )
{
register short i;
i = tabi & (2*QSIZ-1); /* i = tabi % 2QSIZ; */
if ( i & QSIZ ) /* if ( i >= QSIZ ) */
i = 2*QSIZ - i; /* reflect i from the 2nd to the 1st quadrant */
if ( tabi & (2*QSIZ) ) /* if ( (tabi % 4QSIZ) >= 2QSIZ ) */
return -sintab[i]; /* negate sintab[i] if in 3rd or 4th quadrant */
else return sintab[i];
}
/* getusrharm() asks the user for a frequency and returns number of the */
/* closest harmonic of the sine table frequency */
short getusrharm( double rate )
{
double infreq, oufreq, tabfreq, centerr;
short retval;
GET_NUM_RANGE( "frequency", "%.1f", "%lf", infreq, 0.0, rate/2 );
if ( infreq == 0.0 ) return 0;
tabfreq = rate / (4*QSIZ); /* sine table frequency (1) */
retval = infreq / tabfreq + 0.5; /* (2) */
if (!retval) retval++; /* bump 0th harmonic up to 1st */
oufreq = tabfreq * retval; /* output frequency */
if (oufreq > rate/2) { /* if Nyquist freq. exceeded */
oufreq -= tabfreq; /* bump oufreq down 1 harmonic */
retval--; /* bump retval down 1 harmonic */
}
centerr = 1200 * log( oufreq/infreq ) / log(2); /* 3 */
fprintf( stderr, "\tUsing %.3f Hz, %.3f Hz or %.1f cents away\n\n",
oufreq, oufreq - infreq, centerr );
return retval;
}
/*
1. sine table frequency >= 1 Hz ==> 4*QSIZ <= 44100 < 0x10000 ==> 4*QSIZ
fits in an unsigned word.
2. harmonic of tabfreq closest to infreq (+ 0.5 rounds).
3. cent error is the interval between oufreq and infreq
*/